package com.Shuang.exam4;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Objects;
import java.util.function.Consumer;

public class MyArrayList<E> {
    private Object[] elementDate = {};  //存数据
    private int size;  //记录集合中元素个数，同时也是要添加元素的位置
    private static final int DEFAULT_CAPACITY = 10;  //集合默认容量

    //添加元素方法 添加成功返回true
    public boolean add(E e){
        //首先判断集合空间够不够，不够的话要扩容为原来的1.5倍，但是第一次扩容要默认容量为10
        if (size == elementDate.length){
            addCapacity();
        }
        elementDate[size++] = e;  //把元素放到size的位置且size加1
        return true;
    }

    //用于给集合扩容的方法
    private void addCapacity(){
        if (size == 0){ //说明是第一次扩容
            elementDate = new Object[DEFAULT_CAPACITY];
        }else{
            //证明不是第一次扩容，长度要变为原来的1.5倍（长度右移一位相当于变为原来的一半）
            elementDate = Arrays.copyOf(elementDate, elementDate.length + elementDate.length >> 1);
        }
    }

    //根据索引返回元素方法
    public E get(int index){
        //判断索引是否合理
        judgeIndex(index);
        return elementDate(index);
    }

    //定义一个方法用来强转elementDate数组每个元素
    private E elementDate(int index){
        return (E) elementDate[index];
    }

    //判断索引是否合理方法，越界的话抛一个异常出去
    private void judgeIndex(int index){
        if (index < 0 || index >= size){
            throw new IndexOutOfBoundsException(index + "out of max size:" + (size - 1));
        }
    }

    //根据索引删除元素，删除后会返回被删除的元素
    public E remove(int index){
        //先判断索引是否合理
        judgeIndex(index);

        //先存一下当前要删除的元素最后返回出去
        E e = elementDate(index);

        //[0, 1, 2, 3, 4, 5, 6]
        //      index       size 前六个位置都有元素（索引0-5）第七个位置没有元素，size等于6
        //索引在2这个位置，要删掉这个索引，后面的3 4 5要往前移位，6-2-1 = 3 正好是要移位的元素个数
        //如果索引在5这个位置，6-5-1 = 0 说明删除的是最后一个元素，不需要移位
        //所以就判断 size - index - 1 =? 0 为零说明不用移位，大于零说明要移位并且移位的元素就是这个大小的值
        int moveFlag = size - index - 1;
        if (moveFlag != 0){
            //说明删除的是中间的某个索引元素，后面的要向前移位
            /*
            * arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);
            * */
            //将原数组中  索引位置+1开始  拷贝到 目标数组（还是这个数组中） 索引位置开始 拷贝几个？ ---> 就是moveFlag个。
            System.arraycopy(elementDate, index + 1, elementDate, index, moveFlag);
        }

        //移位完了让最后元素位置 size-1 的位置赋值为空，并且size也要减一 并且moveFlag为零的时候直接过来也满足了 不移位将最后一个元素删除
        elementDate[--size] = null;

        return e;
    }

    //获取集合大小的方法
    public int size(){
        return size;
    }

    //forEach方法支持Lambda进行遍历
    public void forEach(MyConsumer<E> action){
        //先判断action是不是空
        Objects.requireNonNull(action);
        for (int i = 0; i < size; i++) {
            action.accept(elementDate(i));
        }

    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (int i = 0; i < size; i++) {
            E e = elementDate(i);
            sb.append(e).append(i == (size - 1) ? "]"  : ", ");
        }
        return sb.toString();
    }
}


